import { Injectable } from "@nestjs/common";
import { OrderEntity } from "./order.entity";
import { InjectRepository } from "@nestjs/typeorm";
import { ILike, IsNull, MoreThanOrEqual, Not, Repository } from "typeorm";
import { Response } from "express";

@Injectable()
export class OrderService {
  constructor(
    @InjectRepository(OrderEntity)
    private readonly orderEntity: Repository<OrderEntity>
  ) {}

  /**
   * Obtain all orders information
   * @param res
   */
  public async getAll(res: Response): Promise<void> {
    const result = await this.orderEntity.find()
    res.json(result)
  }

  /**
   * Obtain all orders information with soft deletion
   * @param res
   */
  public async getAllWithDeleted(res: Response): Promise<void> {
    const result = await this.orderEntity.find({
      withDeleted: true,
      where: {
        deleteAt: Not(IsNull())
      }
    })
    res.json(result)
  }

  /**
   * Soft deletion orders
   * @param body
   * @param res
   */
  async delete(body: any, res: Response): Promise<void> {
    try {
      const { id } = body
      await this.orderEntity.softDelete(id)
      res.json({ status: "success", message: "订单删除成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Real deletion orders
   * @param body
   * @param res
   */
  async remove(body: any, res: Response): Promise<void> {
    try {
      const { id } = body
      await this.orderEntity.delete(id)
      res.json({ status: "success", message: "订单删除成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器被内部错误，请稍后再试！" })
    }
  }

  /**
   * Batch soft deletion orders
   * @param body
   * @param res
   */
  async deleteGroup(body: any, res: Response): Promise<void> {
    const { ids } = body
    try {
      for (let i = 0; i < ids.length; i++) {
        await this.orderEntity.softDelete(ids[i])
      }
      res.json({ status: "success", message: "订单删除成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Batch real deletion orders
   * @param body
   * @param res
   */
  async removeGroup(body: any, res: Response): Promise<void> {
    const { ids } = body
    try {
      for (let i = 0; i < ids.length; i++) {
        await this.orderEntity.delete(ids[i])
      }
      res.json({ status: "success", message: "订单删除成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Soft clear orders of not paid
   * @param res
   */
  public async clear(res: Response): Promise<void> {
    try {
      await this.orderEntity.softDelete({ status: 0 })
      res.json({ status: "success", message: "订单清理成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Search orders
   * @param body
   * @param res
   */
  public async search(body: any, res: Response): Promise<void> {
    try {
      const result = await this.orderEntity.find({
        where: {
          order: ILike(`%${body.order}%`)
        }
      })
      res.json(result)
    } catch (err) {
      console.log(err)
    }
  }

  /**
   * Search orders with soft deletion
   * @param body
   * @param res
   */
  public async searchWithDeleted(body: any, res: Response): Promise<void> {
    try {
      const result = await this.orderEntity.find({
        withDeleted: true,
        where: {
          order: ILike(`%${body.order}%`),
          deleteAt: Not(IsNull())
        }
      })
      res.json(result)
    } catch (err) {
      console.log(err)
    }
  }

  /**
   * Restore orders
   * @param body
   * @param res
   */
  public async restore(body: any, res: Response): Promise<void> {
    try {
      const { id } = body
      await this.orderEntity.update(id, { deleteAt: null })
      res.json({ status: "success", message: "订单信息恢复成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Obtain platform income
   * @param res
   */
  public async count(res: Response): Promise<void> {
    try {
      const result = await this.orderEntity.find({ where: { status: 1 } })
      const income = result.reduce((a, b) => a + Number(b.total), 0)
      res.json(income)
    } catch (err) {
      console.log(err)
    }
  }

  /**
   * Obtain income trend
   * @param res
   */
  public async trend(res: Response): Promise<void> {
    try {
      const lastTenDays = this.getLastTenDays()
      const result = await this.orderEntity.find({
        where: {
          status: 1,
          create_date: MoreThanOrEqual(lastTenDays[0]) // Only obtain current ten days
        },
        select: ["total", "type", "create_date"]
      })

      const data = {
        wechatPay: Array(10).fill(0),
        aliPay: Array(10).fill(0),
        date: lastTenDays
      }

      result.forEach((item) => {
        const index = lastTenDays.indexOf(item.create_date);
        // If there is no operation on a certain day, there is no need to accumulate
        if (index !== -1) {
          // 0 is aliPay, 1 is wechatPay
          if (item.type === 0) {
            data.aliPay[index] += parseFloat(item.total.toFixed(2)); // Round to two decimal places
          } else if (item.type === 1) {
            data.wechatPay[index] += parseFloat(item.total.toFixed(2)); // Round to two decimal places
          }
        }
      })

      // Round the elements in the arrays to two decimal places
      data.aliPay = data.aliPay.map((value) => parseFloat(value.toFixed(2)))
      data.wechatPay = data.wechatPay.map((value) =>
        parseFloat(value.toFixed(2))
      )

      res.json(data)
    } catch (err) {
      console.log(err)
    }
  }

  /**
   * Obtain dated from the last 10 days
   * @private
   */
  private getLastTenDays() {
    const today = new Date()
    const dates = []

    for (let i = 0; i < 10; i++) {
      const currentDate = new Date(today)
      currentDate.setDate(today.getDate() - i)
      const formattedDate = currentDate.toISOString().split("T")[0]
      dates.push(formattedDate)
    }

    return dates.reverse()
  }

  /**
   * Obtain whether the specified order has been paid
   * @param body
   * @param res
   */
  public async isPaid(body: any, res: Response): Promise<void> {
    const { order } = body
    const result = await this.orderEntity.findOne({
      where: { order, status: 1 }
    })
    if (result) {
      res.json({ status: "success", message: "订单已支付！" })
    } else {
      res.json({ status: "error", message: "订单未支付！" })
    }
  }
}
